import * as fs from "fs"
import { Util } from "./Util";
import { ShellUtil } from "./ShellUtil";
/**
 * 目录工具，提供一些方便遍历的操作
 * @author 赵占涛
 */
export class DirUtil {
    /**
     * 递归列出所有文件夹和文件（同步，非异步）
     * @param path 路径
     * @returns 文件（和文件夹）列表
     */
    static getAll(path:string):string[] {
        let retArr:string[] = [];
        this.dirR(path, "", (filePath:string)=>{
            retArr.push(filePath);
        });
        return retArr;
    }
    /**
     * 递归列出所有文件（同步，非异步）
     * @param path 路径
     * @returns 文件列表
     */
    static getAllFile(path:string):string[] {
        let retArr:string[] = [];
        let all = this.getAll(path);
        for (let i = 0; i < all.length; i++) {
            const one = all[i];
            if (!one.endsWith("/")) {
                retArr.push(one);
            }
        }
        return retArr
    }
    /**
     * 递归列出所有文件夹（同步，非异步）
     * @param path 路径
     * @returns 文件夹列表
     */
    static getAllDir(path:string):string[] {
        let retArr:string[] = [];
        let all = this.getAll(path);
        for (let i = 0; i < all.length; i++) {
            const one = all[i];
            if (one.endsWith("/")) {
                retArr.push(one);
            }
        }
        return retArr
    }
    /**
     * 递归列出所有叶子文件夹（同步，非异步），叶子文件夹指的是没有子文件夹的文件夹
     * @param path 路径
     * @returns 文件夹列表
     */
    static getAllLeafDir(path:string):string[] {
        let all = this.getAllDir(path);
        let obj = Util.arrayToObject(all);
        
        for (let i = 0; i < all.length; i++) {
            const one = all[i];
            for (let j = 0; j < all.length; j++) {
                const two = all[j];
                if(two != one && two.indexOf(one) != -1) {
                    delete obj[one];
                }
            }
        }
        return Object.keys(obj);
    }
    private static dirR(basePath: string, dirPath: string, cb: (filePath: string) => void) {
        var files = fs.readdirSync(basePath + dirPath);
        files.sort();
        for (var i = 0; i < files.length; i++) {
            if (files[i].indexOf(".DS_Store") !== -1) {
                continue;
            }
            if (files[i].indexOf(".svn") !== -1) {
                continue;
            }
            var fileOrDirPath = dirPath + files[i];
            var stats = fs.statSync(basePath + fileOrDirPath);
            if (stats.isFile()) {
                cb(fileOrDirPath);
            } else if (stats.isDirectory()) {
                cb(fileOrDirPath + "/")
                this.dirR(basePath, fileOrDirPath + "/", cb);
            }
        }
    }
    /** 确保某个文件所在的文件夹是存在的（不存在就创建） */
    static confirmDirExist(filePath:string, cb:()=>void) {
        let dirPath = filePath.substr(0, filePath.lastIndexOf("/") + 1);
        if (!fs.existsSync(dirPath)) {
            ShellUtil.exec(`
                mkdir -p ${dirPath} || exit 1
            `, cb);
        } else {
            cb();
        }
    }
    /** 查找空文件夹 */
    static findEmptyDir(path:string, cb:(emptyArr:string[])=>void) {
        let allDir = this.getAllLeafDir(path);
        let emptyArr = [];
        for (let i = 0; i < allDir.length; i++) {
            const oneDir = allDir[i];
            var files = fs.readdirSync(path + oneDir);
            let emptyFlag = true;
            for (var j = 0; j < files.length; j++) {
                if (!files[j].startsWith(".")) {
                    emptyFlag = false;
                    break
                }
            }
            if (emptyFlag) {
                emptyArr.push(oneDir);
            }
        }
        cb(emptyArr);
    }
    /** 
     * 删除一个目录的子文件(或文件夹），但是排队一部分文件（或文件夹）
     * 
     */
    /**
     * 删除一个目录的子文件(或文件夹），但是排队一部分文件（或文件夹）
     * @param path 目录
     * @param onlyDeleteDir 是否只会删除文件夹不会删除文件
     * @param excludeArr 要排除的文件（或文件夹）
     * @param cb 完成回调
     */
    static deleteDirChildExcludeSome(path:string, onlyDeleteDir:boolean, excludeArr:{[key:string]:true}, cb:()=>void) {
        var files = fs.readdirSync(path);
        let needDeleteArr:string[] = [];
        for (var i = 0; i < files.length; i++) {
            if (files[i].indexOf(".DS_Store") !== -1) {
                continue;
            }
            if (files[i].indexOf(".svn") !== -1) {
                continue;
            }
            if (!excludeArr[files[i]]) {
                var fileOrDirPath = path + files[i];
                var stats = fs.statSync(fileOrDirPath);
                if (stats.isFile() && !onlyDeleteDir) {
                    needDeleteArr.push(fileOrDirPath);
                } else if (stats.isDirectory()) {
                    needDeleteArr.push(fileOrDirPath);
                }
            }
        }
        if (needDeleteArr.length > 0) {
            let count = 0;
            for (let index = 0; index < needDeleteArr.length; index++) {
                const fileOrDirPath = needDeleteArr[index];
                ShellUtil.exec(`
    rm -rf ${fileOrDirPath} || exit 1
                `, ()=>{
                    count ++;
                    if (count >= needDeleteArr.length) {
                        cb();
                    }
                })
            }
        } else {
            cb();
        }
    }
}